package com.lennon.eoi.executors.export.execl;

import java.io.IOException;
import java.io.OutputStream;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lennon.eoi.autoconfig.ExcelXmlAutoConfig;
import com.lennon.eoi.exception.EOIException;
import com.lennon.eoi.executors.export.AbstractEOIHandler;
import com.lennon.eoi.executors.export.execl.style.ExeclCellStyle;
import com.lennon.eoi.executors.export.execl.style.impl.DefaultUpdateExeclCellStyle;
import com.lennon.eoi.executors.query.EOIQueryList;
import com.lennon.eoi.model.ExcelConfigVO;
import com.lennon.eoi.util.JsonUtil;

/**
 * execl导出
 * 
 * @author lennon
 *
 */
public class EOIExeclHandler<T, E> extends AbstractEOIHandler<T, E> {

	/** 导出的行数*/
    private int rowIndex;
    /** 是否创建表头*/
    private boolean isCreateTitle;
    /** 当前导出execl文件对应得配置文件id*/
    private String excelConfigId;
    /** 导出execl单元格格式*/
    private ExeclCellStyle execlCellStyle;
    
    // 日志
    private Logger logger = LoggerFactory.getLogger(EOIExeclHandler.class);
    
    public EOIExeclHandler(){
        super(null, null);
    }
    
    /**
     * 初始化基本配置
     * 
     * @param eoiQueryList          数据查询器
     * @param queryParamObject      查询的queryObject
     * @param rowIndex              first row
     * @param excelConfigId         execl配置文件的id
     * @param execlCellStyle        execl的单元格格式
     */
    private EOIExeclHandler(EOIQueryList<T, E> eoiQueryList, T queryParamObject,
            int rowIndex, boolean isCreateTitle,String excelConfigId,
            ExeclCellStyle execlCellStyle) {
        super(eoiQueryList, queryParamObject);
        this.rowIndex = rowIndex;
        this.isCreateTitle = isCreateTitle;
        this.excelConfigId = excelConfigId;
        this.execlCellStyle = execlCellStyle;
    }

    // 创建数据
    public static class newBuilder<T, E> {
        
        private T queryParamObject;
        private Integer rowIndex;
        private Boolean isCreateTitle;
        private String excelConfigId;
        private ExeclCellStyle execlCellStyle;
        private EOIQueryList<T, E> eoiQueryList;

        public newBuilder rowIndex(int rowIndex) {
            this.rowIndex = rowIndex;
            return this;
        }
        public newBuilder isCreateTitle(boolean isCreateTitle) {
            this.isCreateTitle = isCreateTitle;
            return this;
        }
        public newBuilder excelConfigId(String excelConfigId) {
            this.excelConfigId = excelConfigId;
            return this;
        }
        public newBuilder execlCellStyle(ExeclCellStyle execlCellStyle) {
            this.execlCellStyle = execlCellStyle;
            return this;
        }

        public newBuilder eoiQueryList(EOIQueryList<T, E> eoiQueryList) {
            this.eoiQueryList = eoiQueryList;
            return this;
        }
        
        public newBuilder queryParamObject(T queryParamObject) {
            this.queryParamObject = queryParamObject;
            return this;
        }
        
        public EOIExeclHandler build() {
            if (rowIndex == null) { rowIndex = 0;   }
            if (isCreateTitle == null) { isCreateTitle = false;}
            if (excelConfigId == null) {throw new EOIException("create execl without config");}
            if (execlCellStyle == null) {execlCellStyle = new DefaultUpdateExeclCellStyle();}
            if (eoiQueryList == null) { throw new EOIException("create execl without queryList");}
            return new EOIExeclHandler(eoiQueryList, queryParamObject,rowIndex, isCreateTitle, excelConfigId, execlCellStyle);
        }
    }
    
    public static newBuilder newBuilder() {
        return new newBuilder();
    }

    @Override
    public void handler(OutputStream outputStream){
        
		// 创建单元格式
		SXSSFWorkbook workbook = new SXSSFWorkbook();
		SXSSFSheet sheet = (SXSSFSheet) workbook.createSheet("Sheet1");
		execlCellStyle.create(workbook);

		// 是否创建表头
		if (isCreateTitle) {
			createTableTitle(workbook, sheet);
		}

		// 写入单元格数据
		createTableBody(workbook, sheet);

		try {
			workbook.write(outputStream);
		} catch (IOException e) {
			logger.error("数据流写入工作簿异常", e);
		} finally {
			if (outputStream != null) {
				try {
					outputStream.flush();
					outputStream.close();
				} catch (IOException e) {
					logger.error("关闭数据流异常", e);
				}
			}
		}
		workbook.dispose();
    }

    /**
     * 创建表头
     * 
     * @param workbook
     * @param sheet
     */
    private void createTableTitle(Workbook workbook, SXSSFSheet sheet) {
        
        // TODO Auto-generated method stub
        Map<String, ExcelConfigVO> configMap = ExcelXmlAutoConfig.getExcelConfigMap(excelConfigId); // 获取导出配置信息

        // 创建行
        SXSSFRow row = (SXSSFRow) sheet.createRow(rowIndex);

        // 循环创建首行单元格
        for (String key : configMap.keySet()) {
            // 创建单元格
            Cell cell = row.createCell(configMap.get(key).getColIndex());
            cell.setCellType(Cell.CELL_TYPE_STRING);
            cell.setCellValue(configMap.get(key).getColName());

            /// 设置对齐方式
            cell.setCellStyle(getStyleAlign(configMap.get(key).getAlign()));
        }
        ++rowIndex;
    }
    
    /**
     * 创建表内容
     * 
     * @param workbook
     * @param sheet
     */
    private void createTableBody(Workbook workbook, SXSSFSheet sheet) {
        
        // TODO Auto-generated method stub
        Map<String, ExcelConfigVO> configMap = ExcelXmlAutoConfig.getExcelConfigMap(excelConfigId); // 获取导出配置信息
        
        // 遍历集合对象创建行和单元格
        for (E e : eoiQueryList.queryList(queryParamObject)) {
            
            HashMap<String, Object> mapData = (HashMap<String, Object>) JsonUtil.objectToMap(e);

            // 创建行
            SXSSFRow row = (SXSSFRow) sheet.createRow(rowIndex);

            // 循环创建第rowIndex行的单元格
            for (String key : configMap.keySet()) {
            	
                // 创建单元格
                Cell cell = row.createCell(configMap.get(key).getColIndex());
                cell.setCellType(configMap.get(key).getCellType());

                String value = String.valueOf(mapData.get(configMap.get(key).getKey())); 
                if (value != null) {
                    if (Cell.CELL_TYPE_NUMERIC == configMap.get(key).getCellType()) {
                        cell.setCellValue(Double.valueOf(value));
                    } else {
                        cell.setCellValue(value);
                    }
                }
                
                // 设置对齐方式
                cell.setCellStyle(getStyleAlign(configMap.get(key).getAlign()));
            }
            rowIndex++;
        }
    }
    
    /**
     * 通过配置文件件中的对齐方式来修正数据在单元格的对齐方式
     * 默认是居中
     * 
     * @param align
     * @return
     */
    private XSSFCellStyle getStyleAlign(short align) {
    	if (align == execlCellStyle.getStyleAlignLeft().getAlignment()) {
            return execlCellStyle.getStyleAlignLeft();
        } else if (align == execlCellStyle.getStyleAlignRight().getAlignment()) {
        	return execlCellStyle.getStyleAlignRight();
        } else {
        	return execlCellStyle.getStyleAlignCenter();
        }
    }
}
